﻿using System;
using System.Collections.Generic;
using TA.JSON;
using System.Text;
using TA.DotNetUtils;
using System.ComponentModel;

namespace TA.Turbo.Controls
{
	/// <summary>
	/// Collection of <see cref="ListItem"/> objects.
	/// </summary>
	public class ListItemCollection : VList<ListItem>, IJsonCompatible, ICloneable, IControlOwned
	{
		#region PUBLIC
		#region INIT
		/// <summary>
		/// Ctor.
		/// </summary>
		public ListItemCollection()
		{
		}
		/// <summary>
		/// Copy ctor.
		/// </summary>
		/// <param name="lic"></param>
		public ListItemCollection(ListItemCollection lic)
		{
			this.AddRange(lic);
		}
		#endregion
		#region PROPS
		TControl IControlOwned.Owner
		{
			get
			{
				return this.Owner;
			}
		}
		#endregion
		#region METHODS
		/// <summary>
		/// Finds and returns an item with the <see cref="ListItem.Text"/> property equal to the specified string.
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		public ListItem FindByText(string text)
		{
			if (!_itemsByText.ContainsKey(text))
				return null;
			return _itemsByText[text];
		}
		/// <summary>
		/// Finds and returns an item with the <see cref="ListItem.Value"/> property equal to the specified string.
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public ListItem FindByValue(string value)
		{
			if (!_itemsByValue.ContainsKey(value))
				return null;
			return _itemsByValue[value];
		}
		/// <summary>
		/// Returns a clone of this instance.
		/// </summary>
		/// <returns></returns>
		public object Clone()
		{
			return new ListItemCollection(this);
		}
		#endregion
		#endregion
		#region INTERNAL
		#region VARS
		internal object _owner;
		internal Dictionary<string, ListItem> _itemsByText = new Dictionary<string, ListItem>();
		internal Dictionary<string, ListItem> _itemsByValue = new Dictionary<string, ListItem>();
		#endregion
		#region PROPS
		internal BaseListControl Owner
		{
			get
			{
				if (this._owner is ListItem)
					return ((ListItem)this._owner).Owner;
				if (this._owner is BaseListControl)
					return (BaseListControl)this._owner;
				return null;
			}
		}
		internal ListItemCollection Collection
		{
			get
			{
				return Owner.Items;
			}
		}
		#endregion
		#region METHODS
		#region EVENTS
		/// <summary>
		/// Called when an item is added to the collection.
		/// </summary>
		/// <param name="item"></param>
		protected override void OnItemAdded(ListItem item)
		{
			base.OnItemAdded(item);

			item._owner = this;

			if (!string.IsNullOrEmpty(item.Text))
				this._itemsByText[item.Text] = item;

			if (!string.IsNullOrEmpty(item.Value))
				this._itemsByValue[item.Value] = item;
		}
		/// <summary>
		/// Called when an item is removed from the collection.
		/// </summary>
		/// <param name="item"></param>
		protected override void OnItemRemoved(ListItem item)
		{
			base.OnItemRemoved(item);

			item._owner = null;

			if (!string.IsNullOrEmpty(item.Text) && this._itemsByText.ContainsKey(item.Text))
				this._itemsByText.Remove(item.Text);

			if (!string.IsNullOrEmpty(item.Value) && this._itemsByValue.ContainsKey(item.Value))
				this._itemsByValue.Remove(item.Value);
		}
		#endregion
		#region IJsonSerializable Members

		bool IJsonSerializable.IsDirty
		{
			get { return this.Count > 0; }
		}

		void IJsonSerializable.Serialize(JsonWriter jw)
		{
			this.SerializeArray(jw);
		}

		void IJsonSerializable.SerializeContents(JsonWriter jw)
		{
			foreach (ListItem li in this)
				((IJsonSerializable)li).Serialize(jw);
		}

		#endregion
		#region IJsonDeserializable Members

		void IJsonDeserializable.Deserialize(IJsonReader jr)
		{
			this.DeserializeArray(jr);
		}

		void IJsonDeserializable.DeserializeContent(IJsonReader jr, string propShortName)
		{
			ListItem li = new ListItem();
			((IJsonDeserializable)li).Deserialize(jr);
			this.Add(li);
		}

		#endregion
		#region IControlOwned Members
		[EditorBrowsable(EditorBrowsableState.Never)]
		void IControlOwned.SetOwner(TControl control)
		{
			this._owner = control;
		}
		#endregion
		#endregion
		#endregion
	}
}
